package com.oschina.bottle.bus;

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.springframework.util.Assert;

/**
 * 事件总线, 配置类
 *
 * @author <a href="mailto:zhongchao@gegejia.com">zhong</a>
 * @version 1.0 2016/12/30
 * @since 1.0
 */
@Configuration
public class EventBusAutoConfiguration {

    @Value("${bus.async.threadPools:5}")
    private Integer threadPools;

    @Bean(name = EventBusConfigUtils.SYNC_EVENT_BUS_BEAN_NAME)
    @Order(2)
    @ConditionalOnProperty(value = "bus.sync.enabled")
    EventBus eventBus() {
        return new EventBus("syncEvent");
    }


    @Bean(name = EventBusConfigUtils.ASYNC_EVENT_BUS_BEAN_NAME)
    @Order(2)
    @ConditionalOnProperty(value = "bus.async.enabled", matchIfMissing = true)
    AsyncEventBus asyncEventBus() {
        Executor executor = new ThreadPoolExecutor(threadPools, threadPools * 2, 60,
            TimeUnit.SECONDS, new LinkedBlockingDeque<>(threadPools * 2));
        return new AsyncEventBus("asyncEvent", executor);
    }

    @Bean(name = EventBusConfigUtils.SUBSCRIBE_ANNOTATION_BEAN_NAME)
    SubscribeAnnotationBeanPostProcessor subscribeAnnotationBeanPostProcessor() {
        return new SubscribeAnnotationBeanPostProcessor();
    }
}
